package model.components.networks.factory;

import java.util.ArrayList;
import java.util.List;

import edu.uci.ics.jung.graph.Graph;

import model.components.links.factory.PhysicalLinksFactory;
import model.components.links.link.Link;
import model.components.networks.network.PhysicalNetwork;
import model.components.nodes.factory.PhysicalNodesFactory;
import model.components.nodes.node.Node;

public class PhysicalNetworksFactory extends NetworksFactory
{	
	public static final String NAME_PREFIX = "PhysicalNetwork";
	public static final int NETWORKS_NUMBER = 5;
	
	public static final int MIN_NODES_NUMBER = 25;
	public static final int MAX_NODES_NUMBER = 25;
	
	public static final String LINKS_NUMBER_TYPE = NetworksFactory.PERCENTAGE;
	public static final int LINKS_NUMBER_PERCENTAGE = 25;
	public static final int MIN_LINKS_NUMBER_RANGE =  1;
	public static final int MAX_LINKS_NUMBER_RANGE = 10;

	public static final int MIN_CPU_PRICE_UNIT = 50;
	public static final int MAX_CPU_PRICE_UNIT = 100;
	
	public static final int MIN_MEMORY_PRICE_UNIT = 50;
	public static final int MAX_MEMORY_PRICE_UNIT = 100;
	
	public static final int MIN_DISK_SPACE_PRICE_UNIT = 50;
	public static final int MAX_DISK_SPACE_PRICE_UNIT = 100;

	public static final int MIN_BANDWIDTH_PRICE_UNIT = 50;
	public static final int MAX_BANDWIDTH_PRICE_UNIT = 100;
	
	private List< PhysicalNetwork > physicalNetworks;
	public List< PhysicalNetwork > getPhysicalNetworks(){ return physicalNetworks; }
	public void setPhysicalNetworks( List< PhysicalNetwork > physicalNetworks ){ this.physicalNetworks = physicalNetworks; }

	public PhysicalNetworksFactory()
	{	
		List< PhysicalNetwork > physicalNetworks = new ArrayList< PhysicalNetwork >();
		
		for( int i = 0; i < NETWORKS_NUMBER; i++ )
		{
			PhysicalNodesFactory physicalNodesFactory = new PhysicalNodesFactory( NAME_PREFIX + i );
			PhysicalLinksFactory physicalLinksFactory = new PhysicalLinksFactory( NAME_PREFIX + i );
			
			Graph< Node, Link > graph = null;
			
			if( LINKS_NUMBER_TYPE.equals( PERCENTAGE ) )
				graph = this.getErdosRenyiGraph( physicalNodesFactory, physicalLinksFactory, MIN_NODES_NUMBER, MAX_NODES_NUMBER, LINKS_NUMBER_PERCENTAGE );
			
			else if( LINKS_NUMBER_TYPE.equals( RANGE ) )
				graph = this.getBarabasiAlbertGraph( physicalNodesFactory, physicalLinksFactory, MIN_NODES_NUMBER, MAX_NODES_NUMBER, MIN_LINKS_NUMBER_RANGE, MAX_LINKS_NUMBER_RANGE );
			
			int cpuUnitPrice = this.randomMinMaxNumber( MIN_CPU_PRICE_UNIT, MAX_CPU_PRICE_UNIT );
			int memoryUnitPrice = this.randomMinMaxNumber( MIN_MEMORY_PRICE_UNIT, MAX_MEMORY_PRICE_UNIT );
			int diskSpaceUnitPrice = this.randomMinMaxNumber( MIN_DISK_SPACE_PRICE_UNIT, MAX_DISK_SPACE_PRICE_UNIT );	
			int bandwidthUnitPrice = this.randomMinMaxNumber( MIN_BANDWIDTH_PRICE_UNIT, MAX_BANDWIDTH_PRICE_UNIT );
			
			physicalNetworks.add( new PhysicalNetwork( NAME_PREFIX, i, graph, cpuUnitPrice, memoryUnitPrice, diskSpaceUnitPrice, bandwidthUnitPrice ) );
		}
		
		this.setPhysicalNetworks( physicalNetworks );
	}
	
	public PhysicalNetworksFactory( String namePrefix, int networksNumber, int minNodesNumber, int maxNodesNumber, int routersPercentage, int switchesPercentage, int serversPercentage, int linuxPercentage, int windowsPercentage, int solarisPercentage, int androidPercentage, int vmWarePercentage, int xenPercentage, int kvmPercentage, int umlPercentage, int minCpu, int maxCpu, int minCpuUnitPrice, int maxCpuUnitPrice, int minMemory, int maxMemory, int minMemoryUnitPrice, int maxMemoryUnitPrice, int minDiskSpace, int maxDiskSpace, int minDiskSpaceUnitPrice, int maxDiskSpaceUnitPrice, int maxVirtualNodesNumber, int linksNumberPercentage, int minBandwidth, int maxBandwidth, int minBandwidthUnitPrice, int maxBandwidthUnitPrice, int minDistance, int maxDistance )
	{	
		List< PhysicalNetwork > physicalNetworks = new ArrayList< PhysicalNetwork >();
		
		for( int i = 0; i < networksNumber; i++ )
		{
			PhysicalNodesFactory physicalNodesFactory = new PhysicalNodesFactory( namePrefix + i, routersPercentage, switchesPercentage, serversPercentage, linuxPercentage, windowsPercentage, solarisPercentage, androidPercentage, vmWarePercentage, xenPercentage, kvmPercentage, umlPercentage, minCpu, maxCpu, minMemory, maxMemory, minDiskSpace, maxDiskSpace, maxVirtualNodesNumber );
			PhysicalLinksFactory physicalLinksFactory = new PhysicalLinksFactory( namePrefix + i, minBandwidth, maxBandwidth, minDistance, maxDistance );
			
			Graph< Node, Link > graph = this.getErdosRenyiGraph( physicalNodesFactory, physicalLinksFactory, minNodesNumber, maxNodesNumber, linksNumberPercentage );
			
			int cpuUnitPrice = this.randomMinMaxNumber( minCpuUnitPrice, maxCpuUnitPrice );
			int memoryUnitPrice = this.randomMinMaxNumber( minMemoryUnitPrice, maxMemoryUnitPrice );
			int diskSpaceUnitPrice = this.randomMinMaxNumber( minDiskSpaceUnitPrice, maxDiskSpaceUnitPrice );	
			int bandwidthUnitPrice = this.randomMinMaxNumber( minBandwidthUnitPrice, maxBandwidthUnitPrice );
			
			physicalNetworks.add( new PhysicalNetwork( namePrefix, i, graph, cpuUnitPrice, memoryUnitPrice, diskSpaceUnitPrice, bandwidthUnitPrice ) );
		}
		
		this.setPhysicalNetworks( physicalNetworks );
	}
	
	public PhysicalNetworksFactory( String namePrefix, int networksNumber, int minNodesNumber, int maxNodesNumber, int routersPercentage, int switchesPercentage, int serversPercentage, int linuxPercentage, int windowsPercentage, int solarisPercentage, int androidPercentage, int vmWarePercentage, int xenPercentage, int kvmPercentage, int umlPercentage, int minCpu, int maxCpu, int minCpuUnitPrice, int maxCpuUnitPrice, int minMemory, int maxMemory, int minMemoryUnitPrice, int maxMemoryUnitPrice, int minDiskSpace, int maxDiskSpace, int minDiskSpaceUnitPrice, int maxDiskSpaceUnitPrice, int maxVirtualNodesNumber, int minLinksNumber, int maxLinksNumber, int minBandwidth, int maxBandwidth, int minBandwidthUnitPrice, int maxBandwidthUnitPrice, int minDistance, int maxDistance )
	{	
		List< PhysicalNetwork > physicalNetworks = new ArrayList< PhysicalNetwork >();
		
		for( int i = 0; i < networksNumber; i++ )
		{			
			PhysicalNodesFactory physicalNodesFactory = new PhysicalNodesFactory( namePrefix + i, routersPercentage, switchesPercentage, serversPercentage, linuxPercentage, windowsPercentage, solarisPercentage, androidPercentage, vmWarePercentage, xenPercentage, kvmPercentage, umlPercentage, minCpu, maxCpu, minMemory, maxMemory, minDiskSpace, maxDiskSpace, maxVirtualNodesNumber );
			PhysicalLinksFactory physicalLinksFactory = new PhysicalLinksFactory( namePrefix + i, minBandwidth, maxBandwidth, minDistance, maxDistance );
			Graph< Node, Link > graph = this.getBarabasiAlbertGraph( physicalNodesFactory, physicalLinksFactory, minNodesNumber, maxNodesNumber, minLinksNumber, maxLinksNumber );
			
			int cpuUnitPrice = this.randomMinMaxNumber( minCpuUnitPrice, maxCpuUnitPrice );
			int memoryUnitPrice = this.randomMinMaxNumber( minMemoryUnitPrice, maxMemoryUnitPrice );
			int diskSpaceUnitPrice = this.randomMinMaxNumber( minDiskSpaceUnitPrice, maxDiskSpaceUnitPrice );	
			int bandwidthUnitPrice = this.randomMinMaxNumber( minBandwidthUnitPrice, maxBandwidthUnitPrice );
			
			physicalNetworks.add( new PhysicalNetwork( namePrefix, i, graph, cpuUnitPrice, memoryUnitPrice, diskSpaceUnitPrice, bandwidthUnitPrice ) );
		}
		
		this.setPhysicalNetworks( physicalNetworks );
	}

}
